<template>
	<div class="antdx6Wrapper">
		<div class="header">111</div>
		<main>
			<div class="left" id="stencil">
				<el-collapse v-model="state.activeNames" @change="handleChange">
					<el-collapse-item title="基础组件" name="1">
						<i
							class="iconfont icon-map-connect-full"
							draggable="true"
							@dragend="handleDragEnd($event, '1')"></i>
					</el-collapse-item>
				</el-collapse>
			</div>
			<div class="center">
				<div id="container"></div>
			</div>
			<!-- 右侧 antd x6 画布配置项 -->
			<div class="right">
				<el-tabs v-model="state.rightTabsActived" class="demo-tabs" @tab-click="handleTabsClick">
					<el-tab-pane label="页面" name="page">
						<el-descriptions :column="1" border size="small">
							<el-descriptions-item label="画布尺寸">
								<SelectSize :selectValue="state.canvasSize" @change="handleCanvasSizeChange" />
							</el-descriptions-item>
							<el-descriptions-item label="背景颜色">
								<el-color-picker
									v-model="state.canvasBgColor"
									size="small"
									show-alpha
									@change="handleCanvasBgColorChange"></el-color-picker>
							</el-descriptions-item>
							<el-descriptions-item label="背景图片">
								<LocalImgUpload
									:maxSize="1"
									@upload-success="handleUploadSuccess"
									@upload-error="handleUploadError" />
							</el-descriptions-item>
							<el-descriptions-item label="辅助网格">
								<el-switch
									v-model="state.canvasGrid"
									:before-change="() => handleCanvasGridChange()"
									active-color="#13ce66"
									inactive-color="#ff4949"
									active-text="开启"
									inactive-text="关闭" />
							</el-descriptions-item>
						</el-descriptions>
					</el-tab-pane>
					<el-tab-pane label="事件" name="event">事件</el-tab-pane>
				</el-tabs>
			</div>
		</main>
	</div>
</template>

<script setup lang="ts">
import { ref, reactive, toRefs, onMounted, computed, h } from 'vue';
import { Graph } from '@antv/x6';
import { Snapline } from '@antv/x6-plugin-snapline';
import { Keyboard } from '@antv/x6-plugin-keyboard';
import { History } from '@antv/x6-plugin-history';
import { Export } from '@antv/x6-plugin-export';
import { CollapseModelValue, ElMessage } from 'element-plus';

import SelectSize from '@/components/SelectSize/index.vue';

// 组件静态数据
const staticData = {};

// 组件状态类型
interface State {
	graph: Graph | null;
	rightTabsActived: string;
	canvasSize: string;
	canvasBgColor: string;
	canvasBgImage: string;
	canvasGrid: boolean;
	activeNames: string[];
}
// 组件内部状态
const state = reactive<State>({
	graph: null, //画布实例对象
	rightTabsActived: 'page',
	canvasSize: '1200*800',
	canvasBgColor: '#f0f0f0',
	canvasBgImage: '',
	canvasGrid: true,
	activeNames: ['1']
});

const width = computed(() => {
	return Number(state.canvasSize.split('*')[0]);
});

const height = computed(() => {
	return Number(state.canvasSize.split('*')[1]);
});

const handleChange = (val: CollapseModelValue) => {
	console.log(val);
};

function handleDragEnd(e: DragEvent, item: any) {
	console.log(e, item);
	const edge = state.graph?.addEdge({
		source: { x: 40, y: 40 },
		target: { x: 380, y: 40 },
		vertices: [
			{ x: 40, y: 80 },
			{ x: 200, y: 80 },
			{ x: 200, y: 40 }
		],
		attrs: {
			line: {
				strokeDasharray: 10,
				strokeWidth: 2,
				targetMarker: 'classic',
				style: {
					animation: 'ant-line 30s infinite linear'
				}
			}
		},
		tools: [
			{
				name: 'button',
				args: {
					markup: [
						{
							tagName: 'circle',
							selector: 'button',
							attrs: {
								r: 18,
								stroke: '#fe854f',
								strokeWidth: 2,
								fill: 'white',
								cursor: 'pointer'
							}
						},
						{
							tagName: 'text',
							textContent: '编辑属性',
							selector: 'icon',
							attrs: {
								fill: '#fe854f',
								fontSize: 10,
								textAnchor: 'middle',
								pointerEvents: 'none',
								y: '0.3em'
							}
						}
					],
					distance: -100,
					onClick({ view }: any) {
						const edge = view.cell;
						if (edge.attr('line/stroke') === 'red') {
							edge.attr('line/stroke', 'black');
						} else {
							edge.attr('line/stroke', 'red');
						}
						// edge.attr('line/stroke', 'red')
					}
				}
			}
		]
	});
	state.graph?.on('edge:mouseenter', ({ cell }) => {
		if (cell === edge) {
			cell.addTools([
				{ name: 'vertices' },
				{
					name: 'source-arrowhead'
				},
				{
					name: 'target-arrowhead',
					args: {
						attrs: {
							fill: 'red'
						}
					}
				},
				{
					name: 'button-remove',
					args: { distance: -40 }
				}
			]);
		}
	});

	state.graph?.on('edge:mouseleave', ({ cell }) => {
		if (cell === edge) {
			if (cell.hasTool('vertices')) {
				cell.removeTool('vertices');
			}
			if (cell.hasTool('source-arrowhead')) {
				cell.removeTool('source-arrowhead');
			}
			if (cell.hasTool('target-arrowhead')) {
				cell.removeTool('target-arrowhead');
			}
			if (cell.hasTool('button-remove')) {
				cell.removeTool('button-remove');
			}
		}
	});

	state.graph?.on('edge:click', ({ edge }) => {
		console.log(edge);

		// if (cell === edge) {
		//   console.log(cell);

		// 	cell.addTools([
		// 		{
		// 			name: 'boundary',
		// 			args: {
		// 				padding: 5,
		// 				attrs: {
		// 					fill: '#7c68fc',
		// 					stroke: '#333',
		// 					strokeWidth: 0.5,
		// 					fillOpacity: 0.2
		// 				}
		// 			}
		// 		}
		// 	]);
		// }
	});
}

// 初始化x6
const initX6 = () => {
	// 确保id为container的dom元素已经挂载到页面上
	console.log(document.getElementById('container'));

	if (document.getElementById('container') === null) {
		const judgeGraphDiv = setInterval(() => {
			if (document.getElementById('container') !== null) {
				console.log('container已挂载');

				window.clearInterval(judgeGraphDiv);
				drawGraph();
			}
		}, 1000);
	} else {
		drawGraph();
	}
};

// 组件挂载完成后初始化x6
const drawGraph = () => {
	state.graph = new Graph({
		container: document.getElementById('container') as HTMLElement,
		width: width.value,
		height: height.value,

		grid: state.canvasGrid,
		// 配置连线规则
		connecting: {
			snap: true, // 自动吸附
			allowBlank: true, // 是否允许连接到画布空白位置的点
			allowMulti: true, // 是否允许在相同的起始节点和终止之间创建多条边
			allowLoop: true, // 是否允许创建循环连线，即边的起始节点和终止节点为同一节点
			highlight: true, // 拖动边时，是否高亮显示所有可用的节点
			allowNode: true, // 是否允许边连接到节点（非节点上的连接桩）
			allowEdge: false, // 是否允许边连接到另一个边
			allowPort: true // 是否允许边连接到连接桩
		},
		background: {
			color: '#f0f0f0'
		},
		panning: false, // 是否开启画布拖拽
		mousewheel: false // 是否开启鼠标滚轮缩放
		// autoResize: true, // 是否开启画布自适应
	});
	state.graph.use(
		new Snapline({
			enabled: true
		})
	);
	state.graph.use(
		new Keyboard({
			enabled: true
		})
	);
	state.graph.use(
		new History({
			enabled: true
		})
	);
};

// 右侧tabs点击事件
const handleTabsClick = (tab: any) => {
	console.log(tab);
};

// 画布尺寸改变
const handleCanvasSizeChange = (size: string) => {
	console.log(size);
	state.canvasSize = size;
	state.graph?.resize(width.value, height.value);
	// 画布背景颜色改变
	state.graph?.drawBackground({
		color: state.canvasBgColor,
		size: {
			width: width.value,
			height: height.value
		},
		image: state.canvasBgImage
	});
};
// 画布背景颜色改变
const handleCanvasBgColorChange = (val: string | null) => {
	if (!val) {
		state.graph?.drawBackground({
			type: 'color',
			color: 'transparent'
		});
		return;
	}
	state.canvasBgColor = val;
	state.graph?.drawBackground({
		color: val
	});
};

// 更改画布背景图片
const handleUploadSuccess = (data: { base64: string; url: string }) => {
	console.log('图片base64:', data.base64);
	console.log('图片URL:', data.url);
	state.canvasBgImage = data.url;
	state.graph?.drawBackground({
		size: {
			width: width.value,
			height: height.value
		},
		image: data.url
	});
};

/** 更改画布网格 */
const handleCanvasGridChange = (): Promise<boolean> => {
	return new Promise((resolve, reject) => {
		console.log('更改画布网格', state.canvasGrid);
		if (state.canvasGrid) {
			state.graph?.hideGrid();
		} else {
			state.graph?.showGrid();
		}
		return resolve(true);
	});
};

const handleUploadError = (error: string) => {
	ElMessage({
		message: error,
		type: 'error'
	});
};
onMounted(() => {
	initX6();
});
</script>
<style scoped lang="scss">
.antdx6Wrapper {
	width: 100%;
	height: 100%;
	display: flex;
	flex-direction: column;

	.header {
		background-color: hotpink;
		height: 50px;
		min-height: 50px;
	}
	main {
		flex: 1;
		background-color: #fff;
		height: calc(100vh - 120px);
		display: flex;
		.left {
			flex: 0 0 200px;
			background-color: #f0f0f0;
			overflow: auto;
			border: 1px solid red;
		}
		.center {
			flex: 1;
			background-color: #f0f0f0;
			overflow: auto;

			border: 1px solid hotpink;
			// position: relative;

			#container {
				width: 100%;
				height: 100%;
				// background-color: rgb(92, 138, 182);
			}
		}
		.right {
			flex: 0 0 250px;
			background-color: #f0f0f0;
			overflow: auto;
			border: 1px solid green;
			padding: 0px 10px;
			.el-tabs {
				height: 100%;
			}
			.demo-tabs > .el-tabs__content {
				padding: 32px;
				color: #6b778c;
				font-size: 32px;
				font-weight: 600;
			}
		}
	}
}
</style>
<style>
@keyframes ant-line {
	to {
		stroke-dashoffset: -1000;
	}
}
</style>
